import html2canvas from 'html2canvas';
import jspdf from 'jspdf';
/**
 * 防抖函数
 * @param {function} fn 事件处理函数
 * @param {number} [delay=20] 延迟时间
 * @param {boolean} [isImmediate=false] 是否立刻执行
 * @param {object} [context=this] 上下文对象
 * @returns {Function} 事件处理函数
 */
export function debounce(fn, delay = 20, isImmediate = false, context = this) {
	// 使用闭包，保存执行状态，控制函数调用顺序
	let timer;
	return function () {
		const _args = [].slice.call(arguments);
		clearTimeout(timer);
		const _fn = function () {
			timer = null;
			if (!isImmediate) fn.apply(context, _args);
		};
		// 是否滚动时立刻执行
		const callNow = !timer && isImmediate;
		timer = setTimeout(_fn, delay);
		if (callNow) fn.apply(context, _args);
	};
}

const raFrame =
	window.requestAnimationFrame ||
	window.webkitRequestAnimationFrame ||
	function (callback) {
		return window.setTimeout(callback, 1000 / 60);
	};

/**
 * 动画延时函数
 * @function
 * @param {function} callback 动画回调函数
 * @return {number} id
 */
export const requestAnimationFrame = raFrame;

/**
 * 清除动画延时
 * @function
 * @param {number} id
 */
export const cancelAnimationFrame =
	window.cancelAnimationFrame ||
	window.webkitRequestAnimationFrame ||
	function (id) {
		window.clearTimeout(id);
	};

/**
 * 节流函数 isLocked在执行中时禁止后续相同函数执行
 * @param {function} fn 事件处理函数
 * @param {boolean} [isImmediate=false] 是否立刻执行
 * @param {object} [context=this] 上下文对象
 * @returns {Function} 事件处理函数
 */
export function throttle(fn, isImmediate = false, context = this) {
	let isLocked;
	return function () {
		const _args = arguments;
		if (isLocked) return;
		isLocked = true;
		raFrame(function () {
			isLocked = false;
			fn.apply(context, _args);
		});
		isImmediate && fn.apply(context, _args);
	};
}

/**
 * 回显数据字典（字符串数组）
 * @param {*} datas 数组原始数据
 * @param {*} value 需要查找的值 多个时按照separator拼接
 * @param {*} separator 多个值时拼接的标识（默认为 , ）
 * @param {*} param2 需要对应的 val和key
 * @returns
 */
export function selectDictLabel(datas, value, separator = ',', { dictValue = 'dictValue', dictLabel = 'dictLabel' } = {}) {
	if (!['', undefined].includes(value)) {
		const actions = [],
			temp = String(value)?.split(separator);
		Object.keys(String(value)?.split(separator)).some((val) => {
			Object.keys(datas).some((key) => {
				if (datas[key][dictValue] == temp[val]) {
					actions.push(datas[key][dictLabel]);
				}
			});
		});
		return actions.join(',');
	}
}

/**
 * 表单重置
 * @param {object} formEl 表单实例  refName
 */
export function resetForm(refName) {
	// 如果传入的refName存在
	if (refName) {
		// 不是公用的my-form标签的ref逻辑
		refName.resetFields?.() || refName.$refs?.refMyForm?.resetFields?.();
	}
}

/**
 * 生成随机GUID
 * @return {string}
 */
export function guid() {
	return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
		.replace(/[xy]/g, function (c) {
			const r = (Math.random() * 16) | 0,
				v = c === 'x' ? r : (r & 0x3) | 0x8;
			return v.toString(16);
		})
		.toUpperCase();
}

// transitionGroup切换定义参数函数
import { customRef } from 'vue';
export function transitionGroupRef(value, delay = 300) {
	return customRef((track, trigger) => ({
		get() {
			track();
			return value;
		},
		set(newValue) {
			value = null;
			trigger();
			setTimeout(() => {
				value = newValue;
				trigger();
			}, delay);
		}
	}));
}

/**
 * 下载 PDF 文件，将指定的 DOM 元素转换为 PDF 格式并下载
 * @param {*} dom 元素实例
 * @param {string} fileName 文件名
 */
export async function downloadPdf(dom, fileName = 'download') {
	// 若传入的 DOM 元素为空，则直接返回
	if (!dom) return;

	try {
		// 利用 html2canvas 将 HTML 元素渲染为 canvas 对象
		const canvas = await html2canvas(dom, { scale: 4 }); // 提高清晰度

		// 创建一个新的 jsPDF 实例，设置为纵向 A4 纸大小
		const pdf = new jspdf('p', 'mm', 'a4');

		// 获取 canvas 的 2D 绘图环境
		const ctx = canvas.getContext('2d');

		// A4 纸的宽度和高度（单位：毫米），预留边距
		const a4w = 190;
		const a4h = 280;

		// 根据 A4 纸的高度和 canvas 的宽度，计算每页图像应有的像素高度
		const imgHeight = Math.floor((a4h * canvas.width) / a4w);

		// 已渲染内容的高度
		let renderedHeight = 0;

		// 循环处理 canvas 内容，分页渲染到 PDF
		while (renderedHeight < canvas.height) {
			// 创建一个新的 canvas 对象，用于处理单页内容
			const page = document.createElement('canvas');
			page.width = canvas.width;
			page.height = Math.min(imgHeight, canvas.height - renderedHeight);

			// 从原 canvas 中剪裁出当前页的内容
			const imageData = ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight));
			page.getContext('2d').putImageData(imageData, 0, 0);

			// 将当前页添加到 PDF 中
			pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 5, a4w, Math.min(a4h, (a4w * page.height) / page.width));

			// 更新已渲染内容的高度
			renderedHeight += imgHeight;

			// 如果还有剩余内容，添加新页面
			if (renderedHeight < canvas.height) {
				pdf.addPage();
			}
		}

		// 保存并命名生成的 PDF 文档
		pdf.save(`${fileName}.pdf`);
	} catch (error) {
		console.error('PDF:', error);
	}
}
